package com.meituan.catering.management.order.biz.service.impl;

import com.meituan.catering.management.common.exception.BizException;
import com.meituan.catering.management.common.model.biz.UserContextBO;
import com.meituan.catering.management.common.model.enumeration.ErrorCode;
import com.meituan.catering.management.order.biz.model.CateringOrderDetailBO;
import com.meituan.catering.management.order.biz.model.converter.CateringOrderDOConverter;
import com.meituan.catering.management.order.biz.model.converter.CateringOrderItemAccessoryDOConverter;
import com.meituan.catering.management.order.biz.model.converter.CateringOrderItemDOConverter;
import com.meituan.catering.management.order.biz.model.request.*;
import com.meituan.catering.management.order.biz.service.CateringOrderBizService;
import com.meituan.catering.management.order.biz.service.CateringOrderQueryService;
import com.meituan.catering.management.order.biz.validator.OrderBizServiceValidator;
import com.meituan.catering.management.order.dao.mapper.CateringOrderItemAccessoryMapper;
import com.meituan.catering.management.order.dao.mapper.CateringOrderItemMapper;
import com.meituan.catering.management.order.dao.mapper.CateringOrderMapper;
import com.meituan.catering.management.order.dao.model.CateringOrderDO;
import com.meituan.catering.management.order.dao.model.CateringOrderItemAccessoryDO;
import com.meituan.catering.management.order.dao.model.CateringOrderItemDO;
import com.meituan.catering.management.order.remote.ProductRemoteService;
import com.meituan.catering.management.order.remote.ShopRemoteService;
import com.meituan.catering.management.order.remote.model.response.ProductDetailRemoteResponse;
import com.meituan.catering.management.order.remote.model.response.ShopDetailRemoteResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CateringOrderBizServiceImpl implements CateringOrderBizService {

    @Resource
    private ShopRemoteService shopRemoteService;

    @Resource
    private ProductRemoteService productRemoteService;

    @Resource
    private CateringOrderQueryService cateringOrderQueryService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private CateringOrderMapper cateringOrderMapper;

    @Resource
    private CateringOrderItemMapper cateringOrderItemMapper;

    @Resource
    private CateringOrderItemAccessoryMapper cateringOrderItemAccessoryMapper;

    @Resource
    private OrderBizServiceValidator orderBizServiceValidator;

    @Override
    public CateringOrderDetailBO place(UserContextBO userContextBO, PlaceCateringOrderBizRequest placeCateringOrderBizRequest) throws BizException {
        ShopDetailRemoteResponse shopRemote = shopRemoteService
                .findByBusinessNo(userContextBO.getTenantId(), userContextBO.getUserId(), placeCateringOrderBizRequest.getShopBusinessNo());
        CateringOrderDO cateringOrderDO = CateringOrderDOConverter.toCateringOrderDO(shopRemote, placeCateringOrderBizRequest, userContextBO);
        //获取请求中订单子项的商品id
        Set<Long> productIds = placeCateringOrderBizRequest.getItems().stream()
                .map(PlaceCateringOrderBizRequest.Item::getProductId)
                .collect(Collectors.toSet());
        List<ProductDetailRemoteResponse> productThriftList = productRemoteService
                .findByIds(userContextBO.getTenantId(), userContextBO.getUserId(), productIds);
        //根据商品id进行分组
        Map<Long, ProductDetailRemoteResponse> productMap = productThriftList.stream()
                .collect(Collectors.toMap(ProductDetailRemoteResponse::getId, item -> item));
        Boolean flag = transactionTemplate.execute(status -> {
            int insertRowCount = cateringOrderMapper.insert(cateringOrderDO);
            if (insertRowCount != 1) {
                status.setRollbackOnly();
                return false;
            }
            List<CateringOrderItemDO> cateringOrderItemDOS = CateringOrderItemDOConverter
                    .toCateringOrderItemDO(placeCateringOrderBizRequest, cateringOrderDO.getId(), userContextBO.getTenantId(), productMap);
            int insertRow = cateringOrderItemMapper.insert(cateringOrderItemDOS);
            if (insertRow != cateringOrderItemDOS.size()) {
                status.setRollbackOnly();
                return false;
            }
            List<CateringOrderItemAccessoryDO> cateringOrderItemAccessoryDOList = CateringOrderItemAccessoryDOConverter.toCateringOrderItemAccessoryDO(
                    userContextBO.getTenantId(), cateringOrderItemDOS, placeCateringOrderBizRequest.getItems(), productMap);
            if (!CollectionUtils.isEmpty(cateringOrderItemAccessoryDOList)) {
                int insert = cateringOrderItemAccessoryMapper.insert(cateringOrderItemAccessoryDOList);
                if (insert != cateringOrderItemAccessoryDOList.size()) {
                    status.setRollbackOnly();
                    return false;
                }
            }
            return true;
        });
        if (!flag) {
            throw new BizException(ErrorCode.SYSTEM_ERROR);
        }
        return cateringOrderQueryService.findById(userContextBO, cateringOrderDO.getId());
    }

    @Override
    public CateringOrderDetailBO prepare(UserContextBO userContextBO, Long orderId, PrepareCateringOrderBizRequest prepareCateringOrderBizRequest) throws BizException {
        CateringOrderDO cateringOrder = cateringOrderMapper.findById(userContextBO.getTenantId(), userContextBO.getUserId(), orderId);
        CateringOrderDO cateringOrderDO = CateringOrderDOConverter.toPrepareCateringOrderDO(cateringOrder, prepareCateringOrderBizRequest.getVersion());
        //订单子项
        List<CateringOrderItemDO> orderItemDOS = cateringOrderItemMapper.findById(userContextBO.getTenantId(), orderId);
        List<CateringOrderItemDO> cateringOrderItemDOList = CateringOrderItemDOConverter.toCateringOrderItemDO(orderId, prepareCateringOrderBizRequest.getItems(),
                orderItemDOS);
        //加料
        Set<Long> orderItemIds = orderItemDOS.stream().map(CateringOrderItemDO::getId).collect(Collectors.toSet());
        List<CateringOrderItemAccessoryDO> accessoryDOS = cateringOrderItemAccessoryMapper.findById(userContextBO.getTenantId(), orderItemIds);
        List<CateringOrderItemAccessoryDO> accessoryDOList = CateringOrderItemAccessoryDOConverter.toItemAccessory(userContextBO, accessoryDOS,
                prepareCateringOrderBizRequest.getItems());
        Boolean flag = transactionTemplate.execute(status -> {
            int prepareRowCount = cateringOrderMapper.update(cateringOrderDO, orderId);
            if (prepareRowCount != 1) {
                status.setRollbackOnly();
                return false;
            }
            int prepareRowTotal = cateringOrderItemMapper.update(cateringOrderItemDOList);
            if (prepareRowTotal != 1) {
                status.setRollbackOnly();
                return false;
            }
            if (!CollectionUtils.isEmpty(accessoryDOList)) {
                int update = cateringOrderItemAccessoryMapper.update(accessoryDOList);
                if (update != accessoryDOList.size()) {
                    status.setRollbackOnly();
                    return false;
                }
            }
            return true;
        });
        if (!flag) {
            throw new BizException(ErrorCode.SYSTEM_ERROR);
        }
        return cateringOrderQueryService.findById(userContextBO, orderId);
    }

    @Override
    public CateringOrderDetailBO produce(UserContextBO userContextBO, Long orderId, ProduceCateringOrderBizRequest produceCateringOrderBizRequest) throws BizException {
        CateringOrderDO cateringOrder = cateringOrderMapper.findById(userContextBO.getTenantId(), userContextBO.getUserId(), orderId);
        CateringOrderDO cateringOrderDO = CateringOrderDOConverter.toProduceCateringOrderDO(cateringOrder, produceCateringOrderBizRequest.getVersion());
        List<CateringOrderItemDO> orderItemDOList = cateringOrderItemMapper.findById(userContextBO.getTenantId(), orderId);
        List<CateringOrderItemDO> cateringOrderItemDO = CateringOrderItemDOConverter.toCateringOrderItem(orderId,
                produceCateringOrderBizRequest.getItems(), orderItemDOList);
        //加料
        Set<Long> orderItemIds = orderItemDOList.stream().map(CateringOrderItemDO::getId).collect(Collectors.toSet());
        List<CateringOrderItemAccessoryDO> accessoryDOS = cateringOrderItemAccessoryMapper.findById(userContextBO.getTenantId(), orderItemIds);
        List<CateringOrderItemAccessoryDO> accessoryDOList = CateringOrderItemAccessoryDOConverter.toItemAccessoryDO(accessoryDOS,
                produceCateringOrderBizRequest.getItems());
        Boolean flag = transactionTemplate.execute(status -> {
            int prepareRowTotal = cateringOrderItemMapper.update(cateringOrderItemDO);
            if (prepareRowTotal != 1) {
                status.setRollbackOnly();
                return false;
            }
            if (!CollectionUtils.isEmpty(accessoryDOList)) {
                int updateRowCount = cateringOrderItemAccessoryMapper.update(accessoryDOList);
                if (updateRowCount != 1) {
                    status.setRollbackOnly();
                    return false;
                }
            }
            //验证加料与订单子项的状态决定订单的状态
            Boolean valid = orderBizServiceValidator.statusValid(userContextBO.getTenantId(), orderId);
            if (valid) {
                int prepareRowCount = cateringOrderMapper.update(cateringOrderDO, orderId);
                if (prepareRowCount != 1) {
                    status.setRollbackOnly();
                    return false;
                }
            }
            return true;
        });
        if (!flag) {
            throw new BizException(ErrorCode.SYSTEM_ERROR);
        }
        return cateringOrderQueryService.findById(userContextBO, orderId);
    }

    @Override
    public CateringOrderDetailBO adjust(UserContextBO userContextBO, Long orderId, AdjustCateringOrderBizRequest adjustCateringOrderBizRequest) throws BizException {
//        CateringOrderDO cateringOrderDO = cateringOrderMapper.findById(userContextBO.getTenantId(), userContextBO.getUserId(), orderId);
//        Set<Long> adjustIds = CateringOrderUtils.getAdjustIds(adjustCateringOrderBizRequest.getItems());
//        List<ProductDetailRemoteResponse> detailRemoteResponses = productRemoteService.findByIds(userContextBO.getTenantId(), userContextBO.getUserId(), adjustIds);
//        Map<Long, ProductDetailRemoteResponse> remoteResponseMap = CateringOrderUtils.groupById(detailRemoteResponses);
//        //订单子项
//        List<CateringOrderItemDO> queryItemList = cateringOrderItemMapper.findById(userContextBO.getTenantId(), orderId);
//        List<CateringOrderItemDO> cateringOrderItemDOS = CateringOrderItemDOConverter
//                .toCateringOrderItemDO(adjustCateringOrderBizRequest.getItems(), orderId, userContextBO.getTenantId(), remoteResponseMap);
//        List<CateringOrderItemDO> orderItemDOInsertList = AdjustCateringItemFilter.itemDOInsertFilterList(cateringOrderItemDOS, queryItemList);
//        List<CateringOrderItemDO> orderItemDOList = AdjustCateringItemFilter.itemDOUpdateFilterList(cateringOrderItemDOS, queryItemList);
//        //加料
//        Set<Long> ids = CateringOrderUtils.getItemDOIds(queryItemList);
//        List<CateringOrderItemAccessoryDO> queryAccessory = cateringOrderItemAccessoryMapper.findById(userContextBO.getTenantId(), ids);
//        Boolean flag = transactionTemplate.execute(status -> {
//            int updateRowCount = cateringOrderItemMapper.update(orderItemDOList);
//            if (updateRowCount != 1) {
//                status.setRollbackOnly();
//                return false;
//            }
//            int insertRowCount = cateringOrderItemMapper.insert(orderItemDOInsertList);
//            if (insertRowCount != orderItemDOInsertList.size()) {
//                status.setRollbackOnly();
//                return false;
//            }
//            List<CateringOrderItemAccessoryDO> accessoryDOList = null;
//            for (AdjustCateringOrderBizRequest.Item item : adjustCateringOrderBizRequest.getItems()) {
//                if (remoteResponseMap.containsKey(item.getProductId())) {
//                    ProductDetailRemoteResponse productDetailRemoteResponse = remoteResponseMap.get(item.getProductId());
////                    accessoryDOList = CateringOrderItemAccessoryDOConverter.toItemAccDO(userContextBO, queryAccessory,
////                            adjustCateringOrderBizRequest.getItems(), productDetailRemoteResponse.getAccessoryGroups());
//                    List<CateringOrderItemAccessoryDO> accessoryDOInsertFilter = AdjustCateringAccessoryFilter.accessoryDOInsertFilter(accessoryDOList, queryAccessory);
//                    int insertCount = cateringOrderItemAccessoryMapper.insert(accessoryDOInsertFilter);
//                    if (insertCount != 1) {
//                        status.setRollbackOnly();
//                        return false;
//                    }
//                }
//            }
//            int updateCount = cateringOrderItemAccessoryMapper.update(AdjustCateringAccessoryFilter.accessoryDOUpdateFilter(accessoryDOList, queryAccessory));
//            if (updateCount != 1) {
//                status.setRollbackOnly();
//                return false;
//            }
//            return true;
//        });
//        if (!flag) {
//            throw new BizException(ErrorCode.SYSTEM_ERROR);
//        }
        return null;
    }

    @Override
    public CateringOrderDetailBO bill(UserContextBO userContextBO, Long orderId, BillCateringOrderBizRequest billCateringOrderBizRequest) {
        CateringOrderDO cateringOrderDO = cateringOrderMapper.findById(userContextBO.getTenantId(), userContextBO.getUserId(), orderId);
        CateringOrderDO orderDO = CateringOrderDOConverter.toCateringOrderDO(cateringOrderDO, billCateringOrderBizRequest);
        int update = cateringOrderMapper.update(orderDO, orderId);
        if (update != 1) {
            return null;
        }
        return cateringOrderQueryService.findById(userContextBO, orderId);
    }
}
